package com.example.aigc_education.integration.impl;

import com.example.aigc_education.common.BusinessException;
import com.example.aigc_education.utils.RedisCache;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.time.Instant;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class CozeTokenIntegrationImpI {

    // OAuth应用配置（需要替换为实际值）
    private static final String OAUTH_APP_ID = "1197143612540"; // OAuth 应用的 ID，在OAuth应用页面查看
    private static final String PUBLIC_KEY_FINGERPRINT = "9HWZCjZIZwLLTVMchvDOP9Rek6zV_D6byFEUV7lqJVY"; // OAuth应用的公钥指纹，在OAuth应用页面查看
    private static final String COZE_API_ENDPOINT = "api.coze.cn"; // 扣子API的Endpoint，固定值
    private static final String COZE_TOKEN_URL = "https://api.coze.cn/api/permission/oauth2/token";

    private static final String COZE_TOKEN_KEY = "sagepath:coze:auth:token";

    @Resource
    private RedisCache redisCache;

    // 从文件加载私钥
    private PrivateKey loadPrivateKey() throws Exception {
        // 使用ClassPathResource加载资源文件
        ClassPathResource resource = new ClassPathResource("coze/private_key.pem");
        String privateKeyContent;

        try (InputStream inputStream = resource.getInputStream()) {
            privateKeyContent = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
        }

        // 移除PEM格式的头尾和换行符
        privateKeyContent = privateKeyContent
                .replace("-----BEGIN PRIVATE KEY-----", "")
                .replace("-----END PRIVATE KEY-----", "")
                .replaceAll("\\s+", "");

        // 解码Base64编码的私钥
        byte[] privateKeyBytes = Base64.getDecoder().decode(privateKeyContent);

        // 创建PKCS8格式的私钥规范
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);

        // 使用RSA算法创建私钥
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return keyFactory.generatePrivate(keySpec);
    }

    public void reFreshCozeToken(){
        // 1. 加载私钥
        PrivateKey privateKey = null;
        try {
            privateKey = loadPrivateKey();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        // 2. 生成JWT
        long now = Instant.now().getEpochSecond();
        String jti = UUID.randomUUID().toString() + UUID.randomUUID().toString();

        String jwt = Jwts.builder()
                .setHeaderParam("alg", "RS256")
                .setHeaderParam("typ", "JWT")
                .setHeaderParam("kid", PUBLIC_KEY_FINGERPRINT)
                .setId(jti)
                .setIssuer(OAUTH_APP_ID)
                .setAudience(COZE_API_ENDPOINT)
                .setIssuedAt(Date.from(Instant.ofEpochSecond(now)))
                .setExpiration(Date.from(Instant.ofEpochSecond(now + 3600)))
                .signWith(privateKey, SignatureAlgorithm.RS256)
                .compact();

        System.out.println("Generated JWT: " + jwt);

        // 3. 准备请求
        RestTemplate restTemplate = new RestTemplate();
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.set("Authorization", "Bearer " + jwt);

        Map<String, Object> requestBody = new HashMap<>();
        requestBody.put("duration_seconds", 86399);
        requestBody.put("grant_type", "urn:ietf:params:oauth:grant-type:jwt-bearer");

        HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(requestBody, headers);

        // 4. 发送请求并重试
        int maxRetries = 3;
        int retryCount = 0;
        boolean success = false;
        ResponseEntity<Map> response = null;

        while (retryCount < maxRetries && !success) {
            try {
                response = restTemplate.exchange(
                        COZE_TOKEN_URL,
                        HttpMethod.POST,
                        requestEntity,
                        Map.class
                );
                success = true;
            } catch (Exception e) {
                retryCount++;
                System.err.println("Failed to get access token, retrying... (" + retryCount + "/" + maxRetries + ")");
                if (retryCount >= maxRetries) {
                    throw new RuntimeException("Failed to get access token after " + maxRetries + " retries", e);
                }
                try {
                    TimeUnit.MILLISECONDS.sleep(1000); // 等待1秒后重试
                } catch (InterruptedException ie) {
                    Thread.currentThread().interrupt();
                    throw new RuntimeException("Thread was interrupted during retry delay", ie);
                }
            }
        }
        Map<String, Object> responseBody = response.getBody();
        //将Token存入Redis数据库
        if (response.getStatusCode() == HttpStatus.OK) {
            String accessToken = (String) responseBody.get("access_token");
            redisCache.setCacheObject(COZE_TOKEN_KEY, accessToken);
        } else {
            throw new BusinessException("Failed to get access token: " + response.getStatusCode());
        }
        log.info("cozeToken refresh success");
    }

    public String getCozeToken() {
        // 1. 从Redis数据库中获取Token
        String accessToken = redisCache.getCacheObject(COZE_TOKEN_KEY);

        // 2. 如果Token不存在，则重新获取Token
        if (accessToken == null) {
            reFreshCozeToken();
            accessToken = redisCache.getCacheObject(COZE_TOKEN_KEY);
        }

        return accessToken;
    }

}
